<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>

<body>

</body>
<script>
  // 工厂模式 (最简单的)  
  // 优点 调用函数,传入对应的参数  就可以 快速得到想要的对象数据

  // 缺点: 
  // 1. 通过函数创建的对象 和 函数没有任何关系
  // 2. 对象中共有的属性和方法重复声明   => 占内存

  // function cat(name, color) {
  //     var obj = {
  //         name: name,
  //         color: color,
  //         species: "cat",
  //         call: function () {
  //             console.log("喵喵");
  //         },
  //         skill: function () {
  //             console.log("捉老鼠");
  //         }
  //     }
  //     return obj;
  // }

  // var Tom = cat("Tom", "black");
  // console.log(Tom);
  // console.log(Tom instanceof cat, Tom instanceof Object);
  // var Kitty = cat("Kitty", "black");
  // console.log(Kitty);

  // 面向对象封装
  // 1. 改写构造函数   =>解决了血缘关系  Tom instanceof Cat => true

  function Cat(name, color) {
    // {}
    // this -> {}
    this.name = name;
    this.color = color;

    // 共有的属性和方法 => 给实例化对象
    // this.species = "cat";
    // this.call = function () {
    //     console.log("喵喵");
    // }
    // this.skill = function () {
    //     console.log("捉老鼠");
    // }
    // return this;
  }


  // 2. 对象中共有的属性和方法重复声明   => 占内存

  // 原型对象 prototype   => {constructor:f}
  // 把共有的属性和方法提取出来 放到构造函数的prototype(Cat.prototype) => 允许所有的实例化对象访问

  // console.dir(Array);  //打印 对象或函数的详细属性和方法
  // 可以理解为函数也是一个特殊的对象  Array.from

  console.dir(Cat);  //打印 对象或函数的详细属性和方法

  Cat.prototype.species = "cat";
  Cat.prototype.call = function () {
    console.log("喵喵");
  }
  Cat.prototype.skill = function () {
    console.log("捉老鼠");
  }

  // 此方法虽然存在原型对象中, 但是调用时 是由实例化对象访问的 Tom.say() =>this指向调用此方法的实例化对象
  Cat.prototype.say = function () {
    console.log(this.name, this.color);
  }

  console.dir(Cat.prototype);



  var Tom = new Cat("Tom", "black");
  console.log(Tom);
  // 自己有访问自己的  
  console.log(Tom.name, Tom.color);

  // 自己没有 则访问构造函数的原型对象(Cat.prototype)
  console.log(Tom.species);
  console.log(Tom.call);
  Tom.call();

  Tom.say();  // 函数调用时 属于谁 this就指向谁  // this -> Tom




  var Kitty = new Cat("Kitty", "pink");
  console.log(Kitty);
  Kitty.say(); // this -> Kitty












</script>

</html>